package br.com.merks.service;

import java.util.List;

import javax.persistence.EntityManager;

import org.apache.log4j.Logger;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.util.jpa.EntityManagerCreator;
import br.com.merks.model.Conf;
import br.com.merks.model.User;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;


@Component
public class UserServiceImpl implements UserService {
	public static final Logger logger = Logger.getLogger(UserServiceImpl.class);
	private EntityManager entityManager;
	private MailService mailService;
	private ConfService confService;
	public UserServiceImpl(EntityManagerCreator emCreator, MailService mailService, ConfService confService) {
		this.entityManager = emCreator.getInstance();
		this.confService = confService;
		this.mailService = mailService;
	}

	public User registerUser(User user) {
		/* Organizando a entrada */
		user.setLogin(user.getLogin().toLowerCase());
		user.setEmailValidToken(User.generateToken());
		Conf conf = this.confService.loadConf();
		user.setMerks(conf.getInitalUserValue());
		this.entityManager.getTransaction().begin();
		entityManager.persist(user);
		this.entityManager.getTransaction().commit();
		return user;
	}

	public User save(User user) {
		entityManager.merge(user);
		
		return user;
	}

	public List<User> list() {
		return this.entityManager.createNamedQuery("user.findAll").getResultList();
	}

	public User find(User user) {
		return  this.entityManager.find(User.class, user.getId());
	}
	
	public User findByLogin(User user) {
		return (User) this.entityManager.createNamedQuery("user.login").setParameter("login", user.getLogin()).getSingleResult();
	}
	
	public User edit(User user) {
		this.entityManager.getTransaction().begin();
		entityManager.merge(user);
		this.entityManager.getTransaction().commit();
		return user;
	}

	public User editAndSaveUser(User user, User sessionUser) {
		// Forcando o id e login do usuario da sessao
		user.setLogin(sessionUser.getLogin()); 
		user.setId(sessionUser.getId());
		logger.debug("Editing user (" + user.getId() + ") " + user.getName());
		//Se modificou o email eh necessario que se valide novamente
		if (!user.getEmail().equals(sessionUser.getEmail())) {  
			user.setEmailValid(0);
			user.setEmailValidToken(User.generateToken());
		} else {
			user.setEmailValid(1);
		}
		// Se o password veio nulo nao eh necessario alterar
		if ((user.getPassword() == null)||(user.getPassword().trim().equals(""))) { 
			logger.debug("Dont Changing user password.");
			user.setPassword(sessionUser.getPassword());
		}
		 user = this.save(user);
		 
		//notificar verificacao de email valido
		if (user.getEmailValid()==0) this.mailService.sendEmail(user, EmailTemplates.getEmailValidationContent());
			
		return user;
	}

	public User validateEmail(String token) {
		logger.debug("Validating email token " + token);
		try {
			User user = (User) this.entityManager.createNamedQuery("user.token").setParameter("token", token).getSingleResult();
			user.setEmailValid(1);
			user.setEmailValidToken("valid");
			user = this.save(user);
			logger.debug("Email validated. " + user.getId() + " " + user.getEmailValid() );
			return user;
		} catch (javax.persistence.NoResultException data) {
			logger.error(data);
			logger.debug("Email not validated. Token not found.");
			return null;
		} catch (javax.persistence.NonUniqueResultException data) {
			logger.error(data);
			logger.debug("Email not validated. Multiple Tokens.");
			return null;
		}

	}
	
	public User performLogin(User user) {
		logger.debug("Making login for " + user.getLogin());
		try {
			User udb = findByLogin(user);
			if (udb!=null) {
			  if(udb.getPassword().equals(user.getPassword())) {
				  logger.debug("Login sucessfully.");
				  return udb;
			  }
		    }
		} catch (javax.persistence.NoResultException data) {
			logger.debug("Login denied. User not Found.");
			return null;
		}
		logger.debug("Login denied. Bad Password.");
		return null;
	}
	public void deleteAll() {
		 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		 
		 Query query = new Query("User");
		 
		 for (Entity taskEntity : datastore.prepare(query).asIterable()) {
			 datastore.delete(taskEntity.getKey());
		 }
	
	}
}
